package com.acmen.easyapi.executor;

import com.acmen.easyapi.model.*;
import com.acmen.easyapi.parse.DataParser;
import com.acmen.easyapi.parse.RequestTableParser;
import com.acmen.easyapi.parse.ResponseTableParser;
import com.acmen.easyapi.provider.DictionaryProvider;
import com.acmen.easyapi.repository.ApiRepository;
import com.acmen.easyapi.repository.AppRepository;
import com.acmen.easyapi.repository.EnvironmentRepository;
import com.acmen.easyapi.util.StringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.ui.ModelMap;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * @author acmen
 * 接口删除执行器
 */
@Component
public class ApiQueryExe {
    @Autowired
    private AppRepository appRepository;
    @Autowired
    private ApiRepository apiRepository;
    @Autowired
    private EnvironmentRepository environmentRepository;
    @Autowired
    private DataParser dataParser;
    @Autowired
    private RequestTableParser requestTableParser;
    @Autowired
    private ResponseTableParser responseTableParser;
    private static final Logger log = LoggerFactory.getLogger(ApiQueryExe.class);
    @Value("${acmen.api.intranetIp:*}")
    private String intranetIp;
    @Autowired
    private DictionaryProvider dictionaryProvider;

    /**
     * 获取API的详细信息，并返回包含API相关信息的ModelMap对象
     * @param request HTTP请求对象
     * @param apiId API的唯一标识符
     * @return 包含API相关信息的ModelMap对象
     */
    public ModelMap apiDetail(HttpServletRequest request, String apiId) {
               ModelMap model = new ModelMap();  // 创建一个ModelMap对象，用于存储模型数据
        model.put("contextPath", request.getContextPath());  // 将请求上下文路径存储到模型数据中
        String path = request.getContextPath();  // 获取请求上下文路径
        String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path;  // 构建基本路径，包括请求的协议、服务器名称、端口和上下文路径
        model.put("basePath", basePath);  // 将基本路径存储到模型数据中
        Api api = apiRepository.selectById(apiId);  // 通过API ID从数据库中查询API对象
        App app = appRepository.selectByName(api.getAppName());  // 通过应用名称从数据库中查询App对象
        model.put("app", app);  // 将App对象存储到模型数据中
        model.put("api", api);  // 将API对象存储到模型数据中
        String servletPath = api.getPath();  // 获取API的servlet路径
        loadDicts(api.getReqParamNode());  // 调用方法加载API的请求参数字典
        loadDicts(api.getResParamNode());  // 调用方法加载API的响应参数字典
        ReqParamNode pathVarNode = api.getReqParamNode().getSubNodes().stream()  // 获取API的路径参数节点
                .filter(e -> e.getName().equalsIgnoreCase(ReqParamNode.NODE_PATH_VAR))  // 过滤出路径变量参数节点
                .findFirst().orElse(null);  // 获取第一个路径变量参数节点，如果没有则设置为null
        if (pathVarNode != null) {
            for (ParamNode node : pathVarNode.getSubNodes()) {  // 遍历路径变量参数节点的子节点
                if (StringUtil.isNotEmpty(node.getExample())) {  // 判断路径变量节点的示例是否为空或非空
                    servletPath = servletPath.replace("{" + node.getName() + "}", node.getExample() + "");  // 将示例值替换到servlet路径中
                } else if (StringUtil.isNotEmpty(node.getExample2())) {  // 判断路径变量节点的第二个示例是否为空或非空
                    servletPath = servletPath.replace("{" + node.getName() + "}", node.getExample2() + "");  // 将第二个示例值替换到servlet路径中
                }
            }
        }

        model.put("servletPath", servletPath);
               // 获取API中的请求参数节点
        ReqParamNode headerNode = api.getReqParamNode().getSubNodes().stream()
                // 过滤出名称为"header"的子节点
                .filter(e -> e.getName().equalsIgnoreCase(ReqParamNode.NODE_HEADER))
                // 如果找到符合条件的子节点，则返回该子节点；否则返回null
                .findFirst().orElse(null);

        // 如果headerNode不为null
        if(headerNode!=null){
            // 将请求头解析后的数据放入模型中
            model.put("requestHeaders", formatJson(dataParser.parseToData(headerNode)));

            // 如果请求中的属性"exportPdf"不为null
            if(request.getAttribute("exportPdf") != null){
                // 解析请求头并将其转换为Table类型的列表
                List<Table> headerTables = requestTableParser.parseToTables(headerNode);

                // 如果headerTables列表不为空
                if(!CollectionUtils.isEmpty(headerTables)){
                    // 将headerTables列表中的第一个Table对象放入模型中
                    model.put("headerTable",headerTables.get(0));
                }
            }
        }


           // 获取请求参数节点
        ReqParamNode paramNode = api.getReqParamNode()
                .getSubNodes().stream()
                .filter(e -> e.getName().equals(ReqParamNode.NODE_PARAM))
                .findFirst().orElse(null);

        // 如果参数节点不为空
        if(paramNode!=null){
            // 如果请求方法是GET或DELETE
            if(api.getRequestMethod().equals(HttpMethod.GET.name())||api.getRequestMethod().equals(HttpMethod.DELETE.name())){
                // 将参数节点解析为Map类型
                Map map = (Map)dataParser.parseToData(paramNode);
                // 如果Map的大小小于等于4
                if(map.size()<=4){
                    // 创建MultiValueMap对象
                    MultiValueMap queryParams = new LinkedMultiValueMap<>();
                    // 遍历Map并将值转换为字符串添加到queryParams中
                    map.forEach((k,v)->{
                        queryParams.add(k,String.valueOf(v));
                    });
                    // 将queryParams转换为查询字符串添加到模型中
                    model.put("queryString", getQueryString(queryParams));
                }else{
                    // 将参数节点的数据格式化为JSON字符串添加到模型中
                    model.put("requestParams", formatJson(dataParser.parseToData(paramNode)));
                }
            }else{
                // 将参数节点的数据格式化为JSON字符串添加到模型中
                model.put("requestParams", formatJson(dataParser.parseToData(paramNode)));
            }
            // 如果存在exportPdf属性
            if(request.getAttribute("exportPdf") != null){
                // 将参数节点解析为Table类型的列表
                List<Table> paramTables = requestTableParser.parseToTables(paramNode);
                // 将paramTables添加到模型中
                model.put("paramTables",paramTables);
            }
        }

              // 获取请求体参数节点
        ReqParamNode bodyNode = api.getReqParamNode().getSubNodes().stream()
                .filter(e->e.getName().equalsIgnoreCase(ReqParamNode.NODE_BODY)).findFirst().orElse(null);

        if(bodyNode!=null){
            // 解析请求体参数为JSON对象
            JSON bodyJson = dataParser.parseToData(bodyNode);
            // 如果解析失败，将请求体参数转为JSON对象
            if(bodyJson == null){
                bodyJson = new JSONObject();
            }
            // 将格式化后的请求体参数放入模型中
            model.put("requestBody", formatJson(bodyJson));

            // 如果请求中存在exportPdf属性
            if(request.getAttribute("exportPdf") != null){
                // 解析请求体参数为表格列表
                List<Table> bodyTables = requestTableParser.parseToTables(bodyNode);
                // 将表格列表放入模型中
                model.put("bodyTables",bodyTables);
            }
        }

        // 将解析后的响应参数放入模型中
        model.put("responseData", formatJson(dataParser.parseToData(api.getResParamNode())));

        // 如果请求中存在exportPdf属性
        if(request.getAttribute("exportPdf") != null){
            // 解析响应参数为表格列表
            List<Table> responseTables = responseTableParser.parseToTables(api.getResParamNode());
            // 将表格列表放入模型中
            model.put("responseTables",responseTables);
        }

        // 获取所有环境并放入模型中
        List<Environment> environments = environmentRepository.getAllByApp(api.getAppName());
        model.put("environments", environments);

        // 获取官方环境并放入模型中
        List<Environment> officialEnvs = environmentRepository.getGatewayEnvironments(api.getAppName());
        model.put("officialEnvs", officialEnvs);

        // 创建一个Section对象并放入模型中
        model.put("section", new Section());

        // 将请求参数节点转为JSON字符串，并替换反斜杠，放入模型中
        model.put("requestNode", JSON.toJSONString(api.getReqParamNode()).replace("\\","\\\\"));

        // 将响应参数节点转为JSON字符串，并替换反斜杠，放入模型中
        model.put("responseNode", JSON.toJSONString(api.getResParamNode()).replace("\\","\\\\"));

        // 获取请求中的Cookie数组
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            // 遍历Cookie数组
            for (Cookie cookie : request.getCookies()) {
                // 将Cookie的名称和值放入模型中
                model.put(cookie.getName(), cookie.getValue());
            }
        }
        // 返回模型
        return model;

    }


    // 加载字典数据
    private void loadDicts(ParamNode paramNode){
        if(StringUtil.isNotEmpty(paramNode.getDictType())){
            // 根据字典类型查询字典列表
            List<Dictionary> dicts = dictionaryProvider.selectList(paramNode.getDictType());
            // 将字典列表转换为字典集合
            List<Dictionary> dictionaries = dicts.stream()
                    .map(d->new Dictionary(String.valueOf(d.getValue()),String.valueOf(d.getLabel())))
                    .collect(Collectors.toList());
            // 设置ParamNode的字典集合
            paramNode.setDictionaries(dictionaries);
        }
        if(paramNode.getSubNodeList() != null){
            // 遍历子节点列表，递归加载字典数据
            paramNode.getSubNodeList().forEach(n->loadDicts(n));
        }
    }

    // 获取查询字符串
    private String getQueryString(MultiValueMap multiValueMap) {
        StringBuffer query = new StringBuffer("?");
        multiValueMap.forEach((key,value)->{
            if(value instanceof List){
                for(Object e : (List)value){
                    // 迭代拼接查询字符串
                    query.append(key +"="+e +"&");
                }
            }else if(value instanceof Map){
                ((Map)value).forEach((k,v)->{
                    // 迭代拼接查询字符串
                    query.append(key+"."+k +"="+v +"&");
                });
            }else{
                // 拼接查询字符串
                query.append(key +"="+value +"&");
            }
        });
        // 去除最后一个"&"
        String queryString = query.toString();
        return queryString.substring(0,queryString.length()-1);
    }


    /**
     * 格式化JSON
     * @param json
     * @return
     */
    private String formatJson(JSON json) {
        if (json == null) {
            return null;
        }
        String string = json.toJSONString();
        string = StringUtil.formatJson(string);
        string = string.replace("\n", "<br/>").replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
        string = string.replace(" ", "&nbsp;");
        return string;
    }

    public static class Section {
        int idx = 0;
        int idx2 = 0;
        static String[] sectins = {"一","二","三","四","五","六","七","八"};
        public String getIndex(){
            idx2 = 0;
            return sectins[idx++];
        }
        public String getIndex2(){
            return idx+"."+(++idx2);
        }
    }
}
